import React, { useEffect, useState } from 'react';
import { AutoComplete, Box, Grid, GridItem, MainColorType, makeToast, Text } from '@nova-hf/ui';
import { OptionsType } from '@nova-hf/ui/umd/ts/src/form-elements/react-select-components/ReactSelectWrapper';
import { useRouter } from 'next/router';
import {
  ContractFieldsToRemove,
  ContractStatus,
  useAddContractDepartmentMutation,
  useContractDepartmentsQuery,
  useContractQuery,
  useContractsDepartmentAndPayerQuery,
  useRemoveFromContractMutation,
  useUpdateDepartmentOnContractMutation,
} from 'typings/graphql';
import { useTranslation } from 'utils/i18n';

import { SettingsButtons } from '../components/SettingsButtons';
import { StillingarLoader } from '../components/StillingarLoader';

export const createOption = (label: string) => ({
  label,
  value: label.toLowerCase().replace(/\W/g, ''),
});

type DepartmentSettingsContainerProps = {
  color: MainColorType;
  contractId?: string;
  isCustomerCompany?: boolean;
};

export const DepartmentSettingsContainer = ({
  color,
  contractId,
  isCustomerCompany,
}: DepartmentSettingsContainerProps) => {
  const { t } = useTranslation('stillingar');
  const { query } = useRouter();
  const serviceId = typeof query?.serviceId === 'string' ? query?.serviceId : '';
  const customerId = typeof query?.customerId === 'string' ? query?.customerId : '';

  const [selectedDepartment, setSelectedDepartment] = useState<OptionsType | undefined>();
  const [departmentOptions, setDepartmentOptions] = useState<OptionsType[]>([]);
  const [currentDepartment, setCurrentDepartment] = useState('');
  const [isEdited, setIsEdited] = useState(false);
  const [addDepartment, { loading: loadingAddDepartment }] = useAddContractDepartmentMutation();

  const { data, loading, error } = useContractsDepartmentAndPayerQuery({
    variables: {
      input: {
        customerId,
        serviceId,
      },
    },
    skip: !serviceId || !customerId,
  });

  const { data: contractData, refetch } = useContractQuery({
    variables: {
      input: {
        id: contractId ?? '',
      },
    },
    skip: !contractId,
  });

  const payerId = contractData?.contract?.payerId;

  const usedCustomerId = payerId === customerId || isCustomerCompany ? customerId : payerId;

  const { data: departmentsData, loading: departmentsLoading } = useContractDepartmentsQuery({
    variables: {
      input: {
        customerId: usedCustomerId ?? '',
      },
    },
    skip: !customerId || !payerId,
  });

  useEffect(() => {
    if (departmentsData && contractData) {
      const findCurrentDepartment = departmentsData?.contractDepartments?.departments?.find(
        (department) => department?.id === contractData?.contract?.departmentId,
      );
      setCurrentDepartment(findCurrentDepartment?.name ?? '');
    }
  }, [departmentsData]);

  const [updateDepartmentOnContract, { loading: loadingUpdateDepartmentOnContract }] =
    useUpdateDepartmentOnContractMutation();

  const [removeDepartmentOnContract, { loading: loadingRemoveDepartmentOnContract }] =
    useRemoveFromContractMutation();

  const contract = data?.contracts.contracts.find(
    (contract) =>
      contract.status === ContractStatus.Active || contract.status === ContractStatus.Pending,
  );

  useEffect(() => {
    if (contract) {
      setIsEdited(contract.departmentId !== selectedDepartment?.value);
    }
  }, [selectedDepartment]);

  useEffect(() => {
    settingInitialSelectedDepartment();
  }, [data]);

  useEffect(() => {
    if (departmentsData && !!departmentsData?.contractDepartments?.departments?.length) {
      const departments: OptionsType[] = departmentsData.contractDepartments?.departments.map(
        (department) => {
          return {
            value: department.id,
            label: department.name,
          };
        },
      );
      setDepartmentOptions(departments);
    }
  }, [departmentsData]);

  const settingInitialSelectedDepartment = () => {
    if (contract) {
      if (contract.departmentName && typeof contract.departmentName === 'string') {
        const selected: OptionsType = {
          label: contract?.departmentName ?? '',
          value: contract?.departmentId ?? '',
        };
        setSelectedDepartment(selected);
        setCurrentDepartment(selected?.label);
      }
    }
  };

  const onCancel = () => {
    settingInitialSelectedDepartment();
  };

  const onSubmit = async () => {
    if (selectedDepartment?.value && selectedDepartment?.value?.length > 0) {
      try {
        const { data: updateDepartmentData } = await updateDepartmentOnContract({
          variables: {
            input: {
              departmentId: selectedDepartment?.value ?? '',
              id: contract?.id ?? '',
            },
          },
        });
        if (updateDepartmentData) {
          makeToast.success(
            t('departmentSettings.updateContractSuccess'),
            t('departmentSettings.updateContractMessage'),
          );
          setCurrentDepartment(selectedDepartment?.label ?? '');
          refetch();
        }
        setIsEdited(false);
      } catch (error) {
        if (error instanceof Error) {
          makeToast.danger(t('departmentSettings.updateContractError'), error.message);
        }
      }
    } else {
      try {
        const { data: removeData } = await removeDepartmentOnContract({
          variables: {
            input: {
              id: contract?.id ?? '',
              fieldsToRemove: [ContractFieldsToRemove.DepartmentId],
            },
          },
        });
        if (removeData) {
          makeToast.success(
            t('departmentSettings.updateContractSuccess'),
            t('departmentSettings.removeDepartmentSuccess'),
          );
          setCurrentDepartment('');
          refetch();
        }
        setIsEdited(false);
      } catch (error) {
        if (error instanceof Error) {
          makeToast.danger(t('departmentSettings.updateContractError'), error.message);
        }
      }
    }
  };

  const handleCreateDepartment = async (inputValue: string) => {
    try {
      const { data: addDepartmentData } = await addDepartment({
        variables: {
          input: {
            customerId: (query.customerId as string) ?? '',
            departmentName: inputValue,
          },
        },
      });
      if (addDepartmentData?.addContractDepartment?.department?.id) {
        makeToast.success(
          t('departmentSettings.addDepartmentSuccess'),
          `${t('departmentSettings.addDepartmentMessage')} ${addDepartmentData
            ?.addContractDepartment?.department.name} `,
        );
        const newOption: OptionsType = {
          label: addDepartmentData?.addContractDepartment?.department?.name,
          value: addDepartmentData?.addContractDepartment?.department?.id,
        };
        setDepartmentOptions((prev) => [...prev, newOption]);
        setSelectedDepartment(newOption);
      } else {
        makeToast.danger(t('departmentSettings.addDepartmentError'), '');
      }
    } catch (error) {
      if (error instanceof Error) {
        makeToast.danger(t('departmentSettings.addDepartmentError'), error.message);
      }
    }
  };

  if (!data || error) return null;
  if (loading) return <StillingarLoader />;

  return (
    <>
      <Box display="flex" flexDirection="column" gap={3}>
        <Text variant="pMediumBold" color="black100">
          {t('departmentSettings.currentDepartment')}
        </Text>
        <Box>
          <Text variant="eyebrowMedium" color="black100">
            {t('departmentSettings.department')}
          </Text>
          <Text>{currentDepartment ?? t('departmentSettings.noDepartment')}</Text>
        </Box>
        <Box>
          <Text variant="pMediumBold" color="black100">
            {t('departmentSettings.changeDepartment')}
          </Text>
          <Text>{t('departmentSettings.description')}</Text>
        </Box>
        <Grid gridTemplate={{ sm: 4, md: 8 }}>
          <GridItem gridColumn={{ sm: 'span4', md: 'span8' }}>
            <AutoComplete
              renderAs="select"
              options={departmentOptions}
              label={t('departmentSettings.departmentLabel')}
              id="department-id"
              placeholder={t('departmentSettings.placeHolder')}
              formatCreateLabel={(val) => `${t('departmentSettings.createDepartmentLabel')} ${val}`}
              noOptionsMessage={() => t('departmentSettings.noDepartmentsLable')}
              onChange={(option) => {
                setSelectedDepartment(option ?? undefined);
              }}
              onCreateOption={handleCreateDepartment}
              value={selectedDepartment}
              isClearable
              instanceId="department-id"
              isDisabled={
                loadingAddDepartment ||
                departmentsLoading ||
                loadingUpdateDepartmentOnContract ||
                loadingRemoveDepartmentOnContract
              }
              color={color}
            />
          </GridItem>
          <GridItem gridColumn={{ sm: 'span4', md: 'span8' }}>
            <SettingsButtons
              cancelButton={{
                text: t('departmentSettings.cancelButton'),
                onClick: onCancel,
                colorScheme: 'white',
                isDisabled:
                  loadingAddDepartment ||
                  loadingUpdateDepartmentOnContract ||
                  !isEdited ||
                  loadingRemoveDepartmentOnContract,
              }}
              confirmButton={{
                text: t('departmentSettings.submitButton'),
                onClick: onSubmit,
                isLoading: loadingUpdateDepartmentOnContract || loadingRemoveDepartmentOnContract,
                isDisabled: loadingAddDepartment || !isEdited,
                dottedShadow: 'none',
                colorScheme: color,
              }}
            />
          </GridItem>
        </Grid>
      </Box>
    </>
  );
};
